﻿using System;
using System.Linq;
using System.Windows;
using System.Reflection;
using System.Windows.Controls;
using System.Collections.Generic;
using System.Activities.Presentation.View;
using System.Activities.Presentation.Hosting;
using System.Activities.Presentation.Model;
using System.ComponentModel.Composition.Hosting;

namespace Vision.VisionWorkshop.Common
{
    /// <summary>
    /// 
    /// </summary>
    public class CustExpressionEditorService : IExpressionEditorService, IDisposable
    {        
        /// <summary>
        /// 
        /// </summary>
        public CustExpressionEditorService()
        {
            
        }

        /// <summary>
        /// 
        /// </summary>
        public void CloseExpressionEditors()
        {

        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="assemblies"></param>
        /// <param name="importedNamespaces"></param>
        /// <param name="variables"></param>
        /// <param name="text"></param>
        /// <param name="initialSize"></param>
        /// <returns></returns>
        public IExpressionEditorInstance CreateExpressionEditor(AssemblyContextControlItem assemblies, ImportedNamespaceContextItem importedNamespaces, List<ModelItem> variables, string text, System.Windows.Size initialSize)
        {
            return this.CreateExpressionEditor(assemblies, importedNamespaces, variables, text, null, initialSize);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="assemblies"></param>
        /// <param name="importedNamespaces"></param>
        /// <param name="variables"></param>
        /// <param name="text"></param>
        /// <returns></returns>
        public IExpressionEditorInstance CreateExpressionEditor(AssemblyContextControlItem assemblies, ImportedNamespaceContextItem importedNamespaces, List<ModelItem> variables, string text)
        {
            return this.CreateExpressionEditor(assemblies, importedNamespaces, variables, text, null, new Size());
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="assemblies"></param>
        /// <param name="importedNamespaces"></param>
        /// <param name="variables"></param>
        /// <param name="text"></param>
        /// <param name="expressionType"></param>
        /// <param name="initialSize"></param>
        /// <returns></returns>
        public IExpressionEditorInstance CreateExpressionEditor(AssemblyContextControlItem assemblies, ImportedNamespaceContextItem importedNamespaces, List<ModelItem> variables, string text, Type expressionType, System.Windows.Size initialSize)
        {
            CustExpressionEditorInstance instance = new CustExpressionEditorInstance(this);
            return instance;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="assemblies"></param>
        /// <param name="importedNamespaces"></param>
        /// <param name="variables"></param>
        /// <param name="text"></param>
        /// <param name="expressionType"></param>
        /// <returns></returns>
        public IExpressionEditorInstance CreateExpressionEditor(AssemblyContextControlItem assemblies, ImportedNamespaceContextItem importedNamespaces, List<ModelItem> variables, string text, Type expressionType)
        {
            return this.CreateExpressionEditor(assemblies, importedNamespaces, variables, text, expressionType, new Size());
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="assemblies"></param>
        /// <param name="importedNamespaces"></param>
        public void UpdateContext(AssemblyContextControlItem assemblies, ImportedNamespaceContextItem importedNamespaces)
        {

        }

        /// <summary>
        /// 
        /// </summary>
        public void Dispose()
        {
            GC.SuppressFinalize(this);    
        }       
    }

    /// <summary>
    /// 
    /// </summary>
    public class CustExpressionEditorInstance : IExpressionEditorInstance
    {
        private CustExpressionEditorService service;
        
        public event EventHandler TextChanged;
        
        public event EventHandler Closing;

        public event EventHandler GotAggregateFocus;

        public event EventHandler LostAggregateFocus;
                        
        private ICSharpCode.AvalonEdit.TextEditor textBox;

        private ICSharpCode.AvalonEdit.CodeCompletion.CompletionWindow completionWindow;

        private ICSharpCode.AvalonEdit.CodeCompletion.InsightWindow insightWindow;

        private List<ModelItem> variables;
                
        public bool AcceptsReturn { get; set; }

        public bool AcceptsTab { get; set; }

        public string Text { get { return this.textBox.Text; } set { this.textBox.Text = value; } }

        public int MaxLines { get; set; }

        public int MinLines { get; set; }

        public bool HasAggregateFocus { get { return true; } }
        
        public System.Windows.Controls.ScrollBarVisibility HorizontalScrollBarVisibility { get; set; }

        public System.Windows.Controls.ScrollBarVisibility VerticalScrollBarVisibility { get; set; }

        public System.Windows.Controls.Control HostControl { get { return this.textBox; } }

        /// <summary>
        /// 
        /// </summary>
        public CustExpressionEditorInstance(IExpressionEditorService editorService)
        {
            this.service = (CustExpressionEditorService)editorService;
            this.Init();
        }
                
        /// <summary>
        /// 
        /// </summary>
        public void Init()
        {                                    
            this.textBox = new ICSharpCode.AvalonEdit.TextEditor();
            this.textBox.BorderThickness = new Thickness(0);
            this.textBox.VerticalScrollBarVisibility = VerticalScrollBarVisibility;
            this.textBox.HorizontalScrollBarVisibility = HorizontalScrollBarVisibility;
               
            this.textBox.SyntaxHighlighting = ICSharpCode.AvalonEdit.Highlighting.HighlightingManager.Instance.GetDefinition("VBNET");
            
            this.textBox.TextArea.TextEntered += new System.Windows.Input.TextCompositionEventHandler(TextArea_TextEntered);
            this.textBox.TextArea.TextEntering += new System.Windows.Input.TextCompositionEventHandler(TextArea_TextEntering);
            
            this.textBox.TextChanged += delegate(object sender, EventArgs e) {
                this.Text = this.textBox.Text;
            };            
        }
                                                    
        /// <summary>
        /// 
        /// </summary>
        public void ClearSelection()
        {
            
        }

        /// <summary>
        /// 
        /// </summary>
        public void Close()
        {
            this.service.Dispose();   
        }               
        
        /// <summary>
        /// 
        /// </summary>
        public void Focus()
        {            
            this.textBox.Focus();            
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public string GetCommittedText()
        {            
            return this.textBox.Text;
        }

        #region bool parms

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public bool CompleteWord()
        {
            return false;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public bool Copy()
        {
            return true;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public bool Cut()
        {
            return true;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public bool DecreaseFilterLevel()
        {
            return false;
        }
        
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public bool GlobalIntellisense()
        {
            return false;
        }               

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public bool IncreaseFilterLevel()
        {
            return false;
        }                

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public bool ParameterInfo()
        {
            return false;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public bool Paste()
        {
            return true;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public bool QuickInfo()
        {
            return false;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public bool Redo()
        {
            return true;
        }
                                
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public bool Undo()
        {
            return true;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public bool CanCompleteWord()
        {
            return false;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public bool CanCopy()
        {
            return true;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public bool CanCut()
        {
            return true;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public bool CanDecreaseFilterLevel()
        {
            return false;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public bool CanGlobalIntellisense()
        {
            return false;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public bool CanIncreaseFilterLevel()
        {
            return false;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public bool CanParameterInfo()
        {
            return false;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public bool CanPaste()
        {
            return true;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public bool CanQuickInfo()
        {
            return false;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public bool CanRedo()
        {
            return true;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public bool CanUndo()
        {
            return true;
        }

        #endregion

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void TextArea_TextEntered(object sender, System.Windows.Input.TextCompositionEventArgs e)
        {
            if (e.Text == "."){
                this.completionWindow = new ICSharpCode.AvalonEdit.CodeCompletion.CompletionWindow(this.textBox.TextArea);
                this.completionWindow.BorderThickness = new Thickness(0);
                
                //IList<ICSharpCode.AvalonEdit.CodeCompletion.ICompletionData> data = completionWindow.CompletionList.CompletionData;
                //if (data != null){
                //    foreach (var v in this.variables){
                //        data.Add(new MyCompletionData(v.ItemType.Name));                        
                //    }                                        
                //}

                this.completionWindow.Show();
                this.completionWindow.Closed += delegate { this.completionWindow = null; };                
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void TextArea_TextEntering(object sender, System.Windows.Input.TextCompositionEventArgs e)
        {
            if (e.Text.Length > 0 && completionWindow != null)
            {
                if (!char.IsLetterOrDigit(e.Text[0]))
                {
                    // Whenever a non-letter is typed while the completion window is open,
                    // insert the currently selected element.
                    completionWindow.CompletionList.RequestInsertion(e);
                }
            }
            // Do not set e.Handled=true.
            // We still want to insert the character that was typed.
        }
    }

    /// <summary>
    /// 
    /// </summary>
    public class MyCompletionData : ICSharpCode.AvalonEdit.CodeCompletion.ICompletionData
    {
        public string Text { get; private set; }

        public object Content { get { return this.Text; } }

        public object Description { get { return "Description for " + this.Text; } }

        public double Priority { get { return 1; } }
        
        public System.Windows.Media.ImageSource Image {get { return null; }}
        
        /// <summary>
        /// 
        /// </summary>
        /// <param name="text"></param>
        public MyCompletionData(string text)
        {
            this.Text = text;
        }
                      
        /// <summary>
        /// 
        /// </summary>
        /// <param name="textArea"></param>
        /// <param name="completionSegment"></param>
        /// <param name="insertionRequestEventArgs"></param>
        public void Complete(ICSharpCode.AvalonEdit.Editing.TextArea textArea, ICSharpCode.AvalonEdit.Document.ISegment completionSegment, EventArgs insertionRequestEventArgs)
        {
            textArea.Document.Replace(completionSegment, this.Text);
        }                
    }
}
